#include "myarray.h"
#include <stdio.h>
#include <stdlib.h>

/**
 * 创建一个数组
 * @param capacity 数组容量
 * @return 返回一个struct MyArray *指针
 */
struct MyArray * MyArray_init(int capacity) {
    if (capacity <= 0) {
        fprintf(stderr, "Capacity must be greater than 0.\n");
        exit(EXIT_FAILURE);
    }
    struct MyArray * p_array = (struct MyArray *) malloc(sizeof(struct MyArray));
    if (!p_array) {
        perror("MyArray_init failure.");
        exit(EXIT_FAILURE);
    }
    int * p_data = (int *) malloc(sizeof(int) * capacity);
    if (!p_data) {
        perror("MyArray -> array init failure.");
        free(p_array);
        exit(EXIT_FAILURE);
    }
    p_array -> size = 0;
    p_array -> capacity = capacity;
    p_array -> array = p_data;
    return p_array;
}

/**
 * 数组扩容
 * @param p_array 待扩容的数组
 */
void MyArray_resize(struct MyArray * p_array) {
    int newCapacity = p_array -> capacity * 2;
    int * p_data = (int *) realloc(p_array -> array, sizeof(int) * newCapacity);
    if (!p_data) {
        perror("MyArray -> array resize failure.");
        free(p_array);
        exit(EXIT_FAILURE);
    }
    p_array -> array = p_data;
    p_array -> capacity = newCapacity;
}

/**
 * 数组插入元素
 * @param p_array 待插入元素的数组
 * @param element 待插入的元素
 * @param index 待插入元素的位置
 */
void MyArray_insert(struct MyArray * p_array, int element, int index) {
    //判断访问下标是否超出范围
    if (index < 0 || index > p_array -> size) {
        fprintf(stderr, "Out of the array's actual element range.\n");
        MyArray_deinit(p_array);
        exit(EXIT_FAILURE);
    }
    //如果实际元素达到数组容量上限，则对数组进行扩容
    if (p_array -> size >= p_array -> capacity) {
        MyArray_resize(p_array);
    }
    //从右向左循环，将元素逐个向右挪1位
    int i = p_array -> size - 1;
    while (i >= index) {
        *(p_array -> array + i + 1) = *(p_array -> array + i);
        --i;
    }
    *(p_array -> array + index) = element;
    ++(p_array -> size);
}

/**
 * 输出数组
 * @param p_array 待输出元素的数组
 */
void MyArray_output(struct MyArray * p_array) {
    int i = 0;
    printf("[");
    while (i < p_array -> size) {
        printf("%d", p_array -> array[i]);
        if (i < p_array -> size - 1) {
            printf(", ");
        }
        ++i;
    }
    printf("]\n");
}

/**
 * 数组删除元素
 * @param p_array 待删除元素的数组
 * @param index 删除的位置
 * @return 被删除的元素
 */
int MyArray_delete(struct MyArray * p_array, int index) {
    int deleteElement = 0;
    //判断访问下标是否超出范围
    if (index < 0 || index >= p_array -> size) {
        fprintf(stderr, "Out of the array's actual element range.\n");
        MyArray_deinit(p_array);
        exit(EXIT_FAILURE);
    }
    deleteElement = *(p_array -> array + index);
    //从右向左循环，将元素逐个向左挪1位
    int i = index;
    while (i < p_array -> size - 1) {
        *(p_array -> array + i) = *(p_array -> array + i + 1);
        ++i;
    }
    --(p_array -> size);

    return deleteElement;
}

/**
 * 释放创建的数组
 * @param p_array 待释放的数组
 */
void MyArray_deinit(struct MyArray * p_array) {
    free(p_array -> array);
    p_array -> array = NULL;
    free(p_array);
    p_array = NULL;
}
